package com.ibm.productivity.tools.blogplugin.views;

import org.eclipse.jface.action.Action;
import org.eclipse.jface.action.IMenuListener;
import org.eclipse.jface.action.IMenuManager;
import org.eclipse.jface.action.IToolBarManager;
import org.eclipse.jface.action.MenuManager;
import org.eclipse.jface.action.Separator;
import org.eclipse.jface.dialogs.MessageDialog;
import org.eclipse.jface.viewers.DoubleClickEvent;
import org.eclipse.jface.viewers.IDoubleClickListener;
import org.eclipse.jface.viewers.ISelection;
import org.eclipse.jface.viewers.IStructuredContentProvider;
import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.jface.viewers.ITreeContentProvider;
import org.eclipse.jface.viewers.LabelProvider;
import org.eclipse.jface.viewers.TreeViewer;
import org.eclipse.jface.viewers.Viewer;
import org.eclipse.jface.viewers.ViewerComparator;
import org.eclipse.swt.SWT;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Menu;
import org.eclipse.ui.IActionBars;
import org.eclipse.ui.ISelectionService;
import org.eclipse.ui.ISharedImages;
import org.eclipse.ui.IWorkbenchActionConstants;
import org.eclipse.ui.IWorkbenchWindow;
import org.eclipse.ui.PlatformUI;
import org.eclipse.ui.part.DrillDownAdapter;
import org.eclipse.ui.part.ViewPart;

import com.ibm.productivity.tools.blogplugin.Activator;
import com.ibm.productivity.tools.blogplugin.BlogDoc;
import com.ibm.productivity.tools.blogplugin.Configure;
import com.ibm.productivity.tools.blogplugin.ExtensionPointGeter;
import com.ibm.productivity.tools.blogplugin.ViewSelectionListener;
import com.ibm.productivity.tools.blogplugin.meta.Article;
import com.ibm.productivity.tools.blogplugin.meta.Comment;
import com.ibm.productivity.tools.ui.RichDocumentViewFactory;
import com.ibm.productivity.tools.ui.views.RichDocumentType;
import com.ibm.productivity.tools.ui.views.RichDocumentView;
import com.sun.star.frame.XModel;
import com.sun.star.text.XText;
import com.sun.star.text.XTextDocument;
import com.sun.star.uno.UnoRuntime;

public class BlogView extends ViewPart {

	public static final String ID = "com.ibm.productivity.tools.blogplugin.views.BlogView";

	public static final int LOGINACTION = 0;
	public static final int LOGOUTACTION = 1;
	public static final int PUBLICACTION = 2;
	public static final int MODIFYACTION = 3;

	private ViewSelectionListener selectionListener;
	private TreeViewer viewer;
	private DrillDownAdapter drillDownAdapter;
	private Action loginAction;
	private Action logoutAction;
	private Action publishAction;
	private Action modifyAction;
	private Action deleteAction;
	private Action openArticleAction;
	private Action plusCommentAction;
	private Action renameTitleAction;

	// Group loginGroup;

	private Composite parent;
	private BlogDoc blogdoc;
	private Image rootImage;
	private Image articleImage;
	private Image commentImage;

	class ViewContentProvider implements IStructuredContentProvider,
			ITreeContentProvider {
		private ArticleParent invisibleRoot;
		private ArticleParent[] roots;

		public void inputChanged(Viewer v, Object oldInput, Object newInput) {

		}

		public void dispose() {

		}

		public Object[] getElements(Object parent) {
			if (parent.equals(getViewSite())) {
				// if (invisibleRoot==null) initialize();
				initialize();
				return getChildren(invisibleRoot);
			}
			return getChildren(parent);
		}

		public Object getParent(Object child) {
			if (child instanceof ArticleNode) {
				return ((ArticleNode) child).getParent();
			}
			return null;
		}

		public Object[] getChildren(Object parent) {
			if (parent instanceof ArticleParent) {
				return ((ArticleParent) parent).getChildren();
			}
			return new Object[0];
		}

		public boolean hasChildren(Object parent) {
			if (parent instanceof ArticleParent)
				return ((ArticleParent) parent).hasChildren();
			return false;
		}

		private void initialize() {
			roots = blogdoc.getArticleTree();
			if (roots == null || Configure.doingLogin == true) {
				roots = new ArticleParent[1];
				if (Configure.doingLogin == false)
					roots[0] = new ArticleParent("Please Login First");
				else
					roots[0] = new ArticleParent("Logining....");
				// root.addChild(new ArticleNode("No article", 0));
			}
			invisibleRoot = new ArticleParent("");
			for (ArticleParent r : roots)
				invisibleRoot.addChild(r);
		}
	}

	class ViewLabelProvider extends LabelProvider {

		public String getText(Object obj) {
			return obj.toString();
		}

		public Image getImage(Object obj) {
			String imageKey = ISharedImages.IMG_OBJ_ELEMENT;
			if (obj instanceof ArticleNode) {
				ArticleNode node = (ArticleNode) obj;
				if (node.getComment() != null)
					return commentImage;
				if (node.getArticle() != null)
					return articleImage;
				return rootImage;
			}
			return PlatformUI.getWorkbench().getSharedImages().getImage(
					imageKey);
		}
	}

	class NameSorter extends ViewerComparator {
		public int category(Object element) {
			return 1;
		}

		public int compare(Viewer viewer, Object e1, Object e2) {
			if ((e1 instanceof ArticleNode) && (e2 instanceof ArticleNode)) {
				ArticleNode a1 = (ArticleNode) e1;
				ArticleNode a2 = (ArticleNode) e2;
				return a1.compareTo(a2);
			}
			return 0;
		}

		public boolean isSorterProperty(Object element, String property) {
			return false;
		}

	}

	public BlogView() {
		// blogdoc = new BlogDoc(new MyMockBlogAccount());
		blogdoc = new BlogDoc(ExtensionPointGeter.getExtensionAccount()[0]);
		Configure.blogView = this;
		rootImage = Activator.getImageDescriptor("icons/blog.gif")
				.createImage();
		articleImage = Activator.getImageDescriptor("icons/article.gif")
				.createImage();
		commentImage = Activator.getImageDescriptor("icons/comment.gif")
				.createImage();

	}

	public void createPartControl(Composite parent) {
		// set parent layout
		this.parent = parent;

		viewer = new TreeViewer(parent, SWT.MULTI | SWT.H_SCROLL | SWT.V_SCROLL);
		drillDownAdapter = new DrillDownAdapter(viewer);
		viewer.setContentProvider(new ViewContentProvider());
		viewer.setLabelProvider(new ViewLabelProvider());
		viewer.setComparator(new NameSorter());
		viewer.setInput(getViewSite());
		makeActions();
		hookContextMenu();
		hookDoubleClickAction();
		contributeToActionBars();
		hookViewSelection();

	}

	private void hookViewSelection() {
		Action[] actions = { loginAction, logoutAction, publishAction,
				modifyAction };
		selectionListener = new ViewSelectionListener(actions, blogdoc);

		IWorkbenchWindow window = PlatformUI.getWorkbench()
				.getActiveWorkbenchWindow();
		ISelectionService service = window.getSelectionService();
		service.addSelectionListener(selectionListener);
	}

	private void hookContextMenu() {
		MenuManager menuMgr = new MenuManager("#PopupMenu");
		menuMgr.setRemoveAllWhenShown(true);
		menuMgr.addMenuListener(new IMenuListener() {
			public void menuAboutToShow(IMenuManager manager) {
				BlogView.this.fillContextMenu(manager);
			}
		});
		Menu menu = menuMgr.createContextMenu(viewer.getControl());
		viewer.getControl().setMenu(menu);
		getSite().registerContextMenu(menuMgr, viewer);
	}

	private void contributeToActionBars() {
		IActionBars bars = getViewSite().getActionBars();
		fillLocalPullDown(bars.getMenuManager());
		fillLocalToolBar(bars.getToolBarManager());
	}

	private void fillLocalPullDown(IMenuManager manager) {
		manager.add(loginAction);
		manager.add(new Separator());
		manager.add(logoutAction);
	}

	private void fillContextMenu(IMenuManager manager) {
		manager.add(deleteAction);
		manager.add(plusCommentAction);
		manager.add(renameTitleAction);
		manager.add(new Separator());
		drillDownAdapter.addNavigationActions(manager);
		// Other plug-ins can contribute there actions here
		manager.add(new Separator(IWorkbenchActionConstants.MB_ADDITIONS));
	}

	private void fillLocalToolBar(IToolBarManager manager) {
		manager.add(loginAction);
		manager.add(logoutAction);
		manager.add(publishAction);
		manager.add(modifyAction);
		manager.add(new Separator());
		drillDownAdapter.addNavigationActions(manager);
	}

	private void makeActions() {

		// the action for login
		loginAction = new Action() {
			public void run() {
				AccountInputDialog in = new AccountInputDialog(parent
						.getShell());
				in.open();
				if (in.getUsername() != null && in.getPassword() != null) {
					final String username = in.getUsername();
					final String password = in.getPassword();
					loginAction.setEnabled(false);
					Configure.canUpdateAction = false;
					Configure.doingLogin = true;
					viewer.refresh();
					
					Thread th = new Thread(new Runnable() {
						public void run() {
							if (blogdoc.login(username, password) == true) {
								Configure.canUpdateAction = true;
								Configure.doingLogin = false;
								Display.getDefault().asyncExec(new Runnable() {
									public void run() {
										viewer.refresh();
										if (blogdoc.getIsLogin() == true) {											
											showMessage("Login Successful.");
											loginAction.setEnabled(false);
											logoutAction.setEnabled(true);
										} else {
											showMessage("Login TimeOut.");
										}
									}
								});
							} else {
								Configure.canUpdateAction = true;
								Configure.doingLogin = false;
								Display.getDefault().asyncExec(new Runnable() {
									public void run() {
										loginAction.setEnabled(true);
										showMessage("Login failed.");
									}
								});
							}
							
						}
					});
					th.start();
				}
			}
		};
		loginAction.setText("Login");
		loginAction.setToolTipText("Login Google Blog");
		loginAction.setImageDescriptor(PlatformUI.getWorkbench()
				.getSharedImages().getImageDescriptor(
						ISharedImages.IMG_TOOL_NEW_WIZARD));

		logoutAction = new Action() {
			public void run() {
				blogdoc.logout();
				blogdoc.buildArticleRoot();
				viewer.refresh();
				loginAction.setEnabled(true);
				logoutAction.setEnabled(false);
				// showMessage("Logout Successful.");
			}
		};
		logoutAction.setText("Logout");
		logoutAction.setToolTipText("Logout Google Account");
		logoutAction.setImageDescriptor(PlatformUI.getWorkbench()
				.getSharedImages().getImageDescriptor(
						ISharedImages.IMG_TOOL_DELETE));
		logoutAction.setEnabled(false);

		publishAction = new Action() {
			public void run() {
				if (blogdoc.getBlogAccount() == null) {
					showMessage("Please Login first.");
					return;
				}
				TitleInputDialog in = new TitleInputDialog(parent.getShell());
				in.setBlogNames(blogdoc.getBlogNames());
				in.open();
				if (in.getTitle() != null) {
					try {
						int index = in.getSelectedIndex();
						// IViewPart part = (IViewPart)
						// PlatformUI.getWorkbench()
						// .getActiveWorkbenchWindow().getActivePage()
						// .getActivePart();
						// if (part.getAdapter(RichDocumentView.class) != null)
						// {
						// System.out.println("I can get the view directly.");
						// } else {
						// System.out
						// .println("I can NOT get the view directly.");
						// }

						// TODO need to change
						// Entry publicPost =
						// blogdoc.getBlogAccount().createPost(
						// index, in.getTitle(),
						// selectionListener.getText(), "Post author",
						// blogdoc.getBlogAccount().getUsername(), false);
						// // blogdoc.buildArticleRoot();
						// blogdoc.addNewNode(index, publicPost);
						// blogdoc.getViewList().add(publicPost,
						// selectionListener.getSelctedView());

						Article a = new Article(in.getTitle(), blogdoc
								.getAuthor(), selectionListener.getText());
						a = blogdoc.getBlogAccount().getBlog(index).postArticle(a);
						blogdoc.addNewNode(index, a);
						blogdoc.getViewList().add(a,
								selectionListener.getSelctedView());

						modifyAction.setEnabled(true);
						publishAction.setEnabled(false);
						viewer.refresh();
						showMessage("Publish article successful.");
					} catch (Exception e) {
						e.printStackTrace();
						showMessage("Error occured.");
					}
				}

				// System.out.println(selectionListener.getText());
				// IWorkbenchWindow window =
				// PlatformUI.getWorkbench().getActiveWorkbenchWindow();
				// ISelectionService service = window.getSelectionService();
				// ISelection selection = service.getSelection();
				// IAdaptable adatable = (IAdaptable)selection;
				// RichDocumentViewSelection viewselection =
				// (RichDocumentViewSelection)adatable.getAdapter(RichDocumentViewSelection.class);
				// RichDocumentView selectedView = viewselection.getView();
				// Object obj = selectedView.getUNOModel();
				// XModel model =
				// (XModel)UnoRuntime.queryInterface(XModel.class, obj);
				// XTextDocument xdoc =
				// (XTextDocument)UnoRuntime.queryInterface(XTextDocument.class,
				// model);
				// XText xdocText = xdoc.getText();
				// System.out.println(xdocText.getString());

			}
		};
		publishAction.setText("Publish");
		publishAction.setToolTipText("Publish the article to blog.");
		publishAction.setImageDescriptor(PlatformUI.getWorkbench()
				.getSharedImages().getImageDescriptor(
						ISharedImages.IMG_TOOL_COPY));

		// not in the menu
		openArticleAction = new Action() {
			public void run() {
				ISelection selection = viewer.getSelection();
				Object obj = ((IStructuredSelection) selection)
						.getFirstElement();
				if (obj instanceof ArticleNode) {
					ArticleNode node = (ArticleNode) obj;
					Article article = node.getArticle();
					Comment comment = node.getComment();
					if (article == null && comment == null)
						return;

					// check it, if it is already opened
					if (blogdoc.getViewList().isNewView(article) == false
							|| blogdoc.getViewList().isNewCommentView(comment) == false) {
						showMessage("The article is already opened.");
						return;
					}

					RichDocumentView newView = RichDocumentViewFactory
							.openView(RichDocumentType.DOCUMENT_TYPE);

					if (node.getID() < ArticleNode.COMMENTSTHRESHOLD) {
						blogdoc.getViewList().add(article, newView);
						modifyAction.setEnabled(true);
						publishAction.setEnabled(false);
					} else {
						blogdoc.getViewList().addComments(comment, newView);
						modifyAction.setEnabled(false);
						publishAction.setEnabled(false);
					}

					// get content
					String content;
					if (article != null)
						content = article.getContent();
					else
						content = comment.getContent();

					// insert content
					Object obj2 = newView.getUNOModel();
					XModel model = (XModel) UnoRuntime.queryInterface(
							XModel.class, obj2);
					XTextDocument xdoc = (XTextDocument) UnoRuntime
							.queryInterface(XTextDocument.class, model);
					XText xdocText = xdoc.getText();
					xdocText.setString(content);

					// save it
					// Date rightNow = new Date();
					// String filename =
					// "c:\\tmp\\"+String.valueOf(rightNow.getTime())+".odt";
					// newView.executeOperation(OperationFactory
					// .createSaveAsOperation(filename));

					// if (LocalSaver.saveFile(node.getID(), title, content))
					// RichDocumentViewFactory.openView(LocalSaver.filename,
					// false);
				}
			}
		};

		modifyAction = new Action() {
			@Override
			public void run() {

				try {
					RichDocumentView view = selectionListener.getSelctedView();
					Article article = blogdoc.getViewList().getArticle(view);
					if (article != null) {
						if (article.getBlog().canUpdateArticle() == true) {
							String content = selectionListener.getText();
							article.setContent(content);
							article = article.getBlog().updateArticle(article);
							showMessage("Update Successful");
						} else {
							showMessage("The Blog Server does NOT support the action.");
						}
					} else {
						showMessage("Can't find the view");
					}

				} catch (Exception e) {
					e.printStackTrace();
					showMessage("Error occured.");
				}
			}
		};
		modifyAction.setText("Modify");
		modifyAction.setToolTipText("Modify the article");
		modifyAction.setImageDescriptor(PlatformUI.getWorkbench()
				.getSharedImages().getImageDescriptor(
						ISharedImages.IMG_TOOL_REDO));

		// not on the menu
		deleteAction = new Action() {
			@Override
			public void run() {
				ISelection selection = viewer.getSelection();
				Object obj = ((IStructuredSelection) selection)
						.getFirstElement();

				if (obj instanceof ArticleNode) {
					ArticleNode node = (ArticleNode) obj;
					Article article = node.getArticle();
					if (article.getBlog().canDeleteArticle() == false) {
						showMessage("The Blog Server does NOT support the action.");
						return;
					}
					String title = node.getName();
					try {
						node.getParent().removeChild(node);
						blogdoc.getViewList().remove(article);
						article.delete();
						viewer.refresh();
						showMessage("Delete " + title + " successful.");
					} catch (Exception e) {
						// e.printStackTrace();
						showMessage("Delete failed.");
					}
				}
			}
		};
		deleteAction.setText("Delete");
		deleteAction.setToolTipText("Delete the article");
		deleteAction.setImageDescriptor(PlatformUI.getWorkbench()
				.getSharedImages().getImageDescriptor(
						ISharedImages.IMG_OBJS_INFO_TSK));

		// not on the menu
		plusCommentAction = new Action() {
			@Override
			public void run() {
				ISelection selection = viewer.getSelection();
				Object obj = ((IStructuredSelection) selection)
						.getFirstElement();
				if (obj instanceof ArticleParent) {
					ArticleParent node = (ArticleParent) obj;
					Article a = node.getArticle();
					if (a.getBlog().canPostComment() == false) {
						showMessage("The Blog Server does NOT support the action.");
						return;
					}
					CommentsInputDialog in = new CommentsInputDialog(parent
							.getShell());
					in.open();
					if (in.getContent() != null) {
						try {
							Comment comment = a.postComment(in.getContent());
							showMessage("Plus New Comment successful.");

							ArticleNode child = new ArticleNode("Comment "
									+ (node.getChildCount() + 1),
									ArticleNode.COMMENTSTHRESHOLD
											+ node.getChildCount());
							child.setComment(comment);
							node.addChild(child);
							viewer.refresh();
						} catch (Exception e) {
							e.printStackTrace();
							showMessage("Plus New Comment failed.");
						}
					}
				}
			}
		};
		plusCommentAction.setText("Plus Comment");
		plusCommentAction.setToolTipText("Plus Comment");
		plusCommentAction.setImageDescriptor(PlatformUI.getWorkbench()
				.getSharedImages().getImageDescriptor(
						ISharedImages.IMG_OBJ_ELEMENT));

		renameTitleAction = new Action() {
			@Override
			public void run() {
				ISelection selection = viewer.getSelection();
				Object obj = ((IStructuredSelection) selection)
						.getFirstElement();
				if (obj instanceof ArticleParent) {
					ArticleParent node = (ArticleParent) obj;
					Article article = node.getArticle();
					String preTitle = article.getTitle();
					if (article.getBlog().canUpdateArticle() == false) {
						showMessage("The Blog Server does NOT support the action.");
						return;
					}
					RenameTitleDialog in = new RenameTitleDialog(parent
							.getShell(), preTitle);
					in.open();
					String newTitle = in.getTitle();
					if (newTitle != null && newTitle.compareTo(preTitle) != 0) {
						article.setTitle(newTitle);
						try {
							article.update();
							node.setName(newTitle);
							viewer.refresh();
						} catch (Exception e) {
							e.printStackTrace();
							showMessage("error occured");
						}
					}
					// CommentsInputDialog in = new CommentsInputDialog(parent
					// .getShell());
					// in.open();
					// if (in.getContent() != null) {
					// try {
					// Entry commentEntry = blogdoc.getBlogAccount()
					// .createComment(entry, in.getContent());
					// if (commentEntry == null)
					// throw new Exception("Can't create new comment.");
					// showMessage("Plus New Comment successful.");
					// // blogdoc.buildArticleRoot();
					// ArticleNode child = new ArticleNode("Comment "
					// + (node.getChildCount() + 1),
					// ArticleNode.COMMENTSTHRESHOLD
					// + node.getChildCount());
					// child.setEntry(commentEntry);
					// node.addChild(child);
					// viewer.refresh();
					// } catch (Exception e) {
					// e.printStackTrace();
					// showMessage("Plus New Comment failed.");
					// }
					// }
				}
			}
		};
		renameTitleAction.setText("Rename Title");
		renameTitleAction.setToolTipText("Rename Title");
		renameTitleAction.setImageDescriptor(PlatformUI.getWorkbench()
				.getSharedImages().getImageDescriptor(
						ISharedImages.IMG_OBJ_ELEMENT));

	}

	private void hookDoubleClickAction() {
		viewer.addDoubleClickListener(new IDoubleClickListener() {
			public void doubleClick(DoubleClickEvent event) {
				openArticleAction.run();
			}
		});
	}

	private void showMessage(String message) {
		MessageDialog.openInformation(viewer.getControl().getShell(),
				"BlogView", message);
	}

	public void setFocus() {
		viewer.getControl().setFocus();
	}

	public BlogDoc getBlogDoc() {
		return blogdoc;
	}

	@Override
	public void dispose() {
		rootImage.dispose();
		articleImage.dispose();
		commentImage.dispose();
		super.dispose();
	}
}